use axum::{
    Json,
    http::{ Request, HeaderMap },
    response::Response,
    middleware::Next,
    body::Body
};
use serde_json::Value;

use crate::{auth::claims::get_token, code, encrypt};

use super::jwt::{token_decode, Claims};

pub fn get_claims(header:HeaderMap) -> Result<Claims, Json<Value>> { token_decode(Some(&get_token(header)?), false) }
pub fn get_id(header:HeaderMap ) -> Result<i32, Json<Value>> {
    Ok( get_claims(header)?.id )
}
pub fn get_ident(header:HeaderMap ) -> Result<String, Json<Value>> {
    let ident = get_claims(header)?.ident;
    let ident = encrypt::magic_crypt::decode_64(&ident)?;
    Ok( ident )
}
pub fn get_veri(header:HeaderMap ) -> Result<String, Json<Value>> {
    let veri = get_claims(header)?.veri;
    let veri = encrypt::magic_crypt::decode_64(&veri)?;
    Ok( veri )
}
pub fn get_casc(header:HeaderMap ) -> Result<Option<String>, Json<Value>> {
    Ok(get_claims(header)?.casc)
}

pub async fn get_req_claims<T:Fn(Claims)->Result<(),Json<Value>>>(req: Request<Body>, next: Next, is_exp:bool, callback:T) -> Result<Response, Json<Value>> {
    let mut err = false;
    if let Some(f) = req.headers().get(http::header::AUTHORIZATION){
        if let Ok(d) = f.to_str() {
            if d.to_owned().contains("Undefined") {
                err = true;
            }else{
                let claims = token_decode(Some(d), is_exp)?;
                callback(claims)?;
            }
        }else{
            err = true;
        }
    }else {
        err = true;
    }
    if err {
        Err( code::fail_(201) )
    }else{
        Ok(next.run(req).await)
    }
}
pub async fn get_req_role<T:Fn(Option<i32>)->Result<(),Json<Value>>>(req: Request<Body>, next: Next, callback:T) -> Result<Response, Json<Value>> {
    get_req_claims(req, next, false,|d| callback(d.role)).await
}